/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_products/gitsolo.htm
 *
 * gitsolo is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.gitsolo.presenter;

import java.io.File;

import org.zhiqim.git.GitServer;
import org.zhiqim.gitsolo.Gitsolo;
import org.zhiqim.gitsolo.GitsoloConstants;
import org.zhiqim.gitsolo.dao.GitProjectDao;
import org.zhiqim.gitsolo.dbo.GitProject;
import org.zhiqim.gitsolo.dbo.GitRepository;
import org.zhiqim.httpd.HttpRequest;
import org.zhiqim.httpd.context.annotation.AnIntercept;
import org.zhiqim.httpd.validate.ones.IsNotEmpty;
import org.zhiqim.kernel.Global;
import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.util.Files;
import org.zhiqim.kernel.util.Randoms;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.manager.ZmrSessionUser;
import org.zhiqim.manager.dao.ZmrOperatorDao;
import org.zhiqim.manager.dbo.ZmrOperator;
import org.zhiqim.orm.ORM;
import org.zhiqim.orm.dbo.Selector;
import org.zhiqim.orm.dbo.Updater;

/**
 * Git展示器
 *
 * @version v1.0.0 @author zouzhigang 2017-12-14 新建与整理
 */
@AnAlias("GitRepositoryPresenter")
@AnIntercept("chkZmrLogin")
public class GitRepositoryPresenter implements GitsoloConstants
{
    /****************************************************************************************************/
    //仓库重命名&迁移相关方法
    /****************************************************************************************************/
    
    /**
     * 重命名仓库编码，先修改文件夹名称，成功后再修改数据库
     * 
     * @param request           请求
     * @param repositoryId      仓库编号
     * @param newRepositoryCode 新仓库编码
     * @throws Exception        异常
     */
    public static void rename(HttpRequest request, long repositoryId, String newRepositoryCode) throws Exception
    {
        if (!Validates.isFileName(newRepositoryCode))
        {
            request.setResponseError("新仓库编码不合法，请重选一个编码");
            return;
        }
        
        GitRepository item = ORM.table().item(GitRepository.class, repositoryId);
        if (item == null)
        {
            request.setResponseError("该仓库不存在");
            return;
        }
        
        if (!GitProjectDao.chkProjectId(request, item.getProjectId()))
        {//判断是否切换了默认项目
            return;
        }
        
        if (newRepositoryCode.equals(item.getRepositoryCode()))
        {//相同不处理
            request.setResponseError("新仓库编码未修改");
            return;
        }
        
        //判断是否存在相同的
        Selector selector = new Selector();
        selector.addMust("projectId", item.getProjectId());
        selector.addMust("repositoryCode", newRepositoryCode);
        selector.addMustNotEqual("repositoryId", repositoryId);
        if (ORM.table().count(GitRepository.class, selector) > 0)
        {
            request.setResponseError("新仓库编码["+newRepositoryCode+"]在该工程下已存在，请重选一个编码");
            return;
        }
        
        String repositoryPath = Gitsolo.getRepositoryPath(item.getProjectId(), item.getRepositoryCode());
        
        GitServer server = Global.getService(GitServer.class);
        String gitRootPath = server.getRootPath(repositoryPath);
        
        //1.删除Git缓存
        server.remove(gitRootPath);
        
        //2.重命名文件夹
        String newRepositoryPath = Gitsolo.getRepositoryPath(item.getProjectId(), newRepositoryCode);
        String newGitRootPath = server.getRootPath(newRepositoryPath);
        File file = new File(gitRootPath);
        if (!file.renameTo(new File(newGitRootPath)))
        {
            request.setResponseError("新仓库编码["+newRepositoryCode+"]重命名失败，请重试");
            return;
        }
        
        //3.修改到数据库
        Updater updater = new Updater();
        updater.addMust("repositoryId", repositoryId);
        updater.addField("repositoryCode", newRepositoryCode);
        ORM.table().update(GitRepository.class, updater);
    }
    
    /**
     * 迁移仓库到新的项目下
     * 
     * @param request       请求
     * @param repositoryId  仓库编号
     * @param destProjectId 新的项目编号
     * @throws Exception    异常
     */
    public static void move(HttpRequest request, long repositoryId, long destProjectId) throws Exception
    {
        GitRepository item = ORM.table().item(GitRepository.class, repositoryId);
        if (item == null)
        {
            request.setResponseError("该仓库不存在");
            return;
        }
        
        if (!GitProjectDao.chkProjectId(request, item.getProjectId()))
        {//判断是否切换了默认项目
            return;
        }
        
        if (ORM.table().count(GitProject.class, destProjectId) == 0)
        {
            request.setResponseError("请选择一个有效的目标项目");
            return;
        }
        
        String repositoryCode = item.getRepositoryCode();
        if (ORM.table().count(GitRepository.class, new Selector("projectId", destProjectId).addMust("repositoryCode", item.getRepositoryCode())) > 0)
        {
            request.setResponseError("目标项目已有["+repositoryCode+"]仓库编码，请先重命名后再迁移");
            return;
        }
        
        //检查工程文件夹是否存在
        GitServer server = Global.getService(GitServer.class);
        String newProjectDir = server.getRootPath("/" + destProjectId);
        Files.mkDirectory(newProjectDir);
        
        String repositoryPath = Gitsolo.getRepositoryPath(item.getProjectId(), item.getRepositoryCode());
        String gitRootPath = server.getRootPath(repositoryPath);
        
        //1.删除Git缓存
        server.remove(gitRootPath);
        
        //2.迁移文件夹到新的工程下
        String newRepositoryPath = Gitsolo.getRepositoryPath(destProjectId, item.getRepositoryCode());
        String newGitRootPath = server.getRootPath(newRepositoryPath);
        File file = new File(gitRootPath);
        if (!file.renameTo(new File(newGitRootPath)))
        {
            request.setResponseError("迁移到新项目["+destProjectId+"]失败，请重试");
            return;
        }
        
        //3.修改到数据库
        Updater updater = new Updater();
        updater.addMust("repositoryId", repositoryId);
        updater.addField("projectId", destProjectId);
        ORM.table().update(GitRepository.class, updater);
    }
    
    /****************************************************************************************************/
    //独立密钥相关方法
    /****************************************************************************************************/
    
    /**
     * 从用户会话中读取Gitsolo独立密钥
     * 
     * @param sessionUser   用户会话对象
     */
    public static String getSecret(ZmrSessionUser sessionUser)
    {
        String secret = sessionUser.getOperatorParam(GIT_SECRET_KEY);
        if (Validates.isEmptyBlank(secret))
            return null;
        
        return secret;
    }
    
    /**
     * 获取Gitsolo独立密钥，要求验证操作员密码
     * 
     * @param request       请求
     * @throws Exception    异常
     */
    public static void getSecretValidate(HttpRequest request) throws Exception
    {
        request.addValidate(new IsNotEmpty("operatorPass", "密码不能为空"));
        if (!request.chkValidate())
        {
            request.setResponseError(request.getAlertMsg());
            return;
        }
        
        ZmrSessionUser sessionUser = request.getSessionUser(ZmrSessionUser.class);
        String operatorPass = request.getParameter("operatorPass");
        if (!ZmrOperatorDao.validatePassword(request, sessionUser.getOperator(), operatorPass))
        {//密码不正确
            request.setResponseError("密码不正确");
            return;
        }
        
        request.setResponseResult(getSecret(sessionUser));
    }
    
    /**
     * 设置Gitsolo独立密码
     * 
     * @param request   请求
     * @throws Exception    异常
     */
    public static void setSecret(HttpRequest request) throws Exception
    {
        ZmrSessionUser sessionUser = request.getSessionUser(ZmrSessionUser.class);
        
        //1.把密码设置到数据库
        String secret = Randoms.lowerLettersDigits(32);
        
        ZmrOperatorDao.addOrUpdateOperatorParam(request, sessionUser.getOperatorCode(), GIT_SECRET_KEY, secret);
        
        //2.更新sessionUser
        ZmrOperator operator = ORM.table().item(ZmrOperator.class, sessionUser.getOperatorCode());
        sessionUser.setOperator(operator);
    }
    
    /**
     * 关闭Gitsolo独立密码
     * 
     * @param request   请求
     * @throws Exception    异常
     */
    public static void closeSecret(HttpRequest request) throws Exception
    {
        ZmrSessionUser sessionUser = request.getSessionUser(ZmrSessionUser.class);
        
        //1.从数据库删除独立密码
        ZmrOperatorDao.deleteOperatorParam(request, sessionUser.getOperatorCode(), GIT_SECRET_KEY);
        
        //2.更新sessionUser
        ZmrOperator operator = ORM.table().item(ZmrOperator.class, sessionUser.getOperatorCode());
        sessionUser.setOperator(operator);
    }
}
